﻿using Microsoft.AspNetCore.Http;
using Separation.Token;
using Separation.Token.Entity;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using Newtonsoft.Json;

namespace Separation.Token
{
    public class TokenAuth
    {
        /// <summary>
        /// http委托
        /// </summary>
        readonly RequestDelegate next;

        public TokenAuth(RequestDelegate _next) 
        {
            next = _next;
        }

        public Task Invoke(HttpContext httpContext) 
        {
            var headers = httpContext.Request.Headers;
            //检测是否包含'Authorization'请求头，如果不包含返回context进行下一个中间件，用于访问不需要认证的API
            if (!headers.ContainsKey("Authorization")) 
            {
                return next(httpContext);
            }

            var token = headers["Authorization"].ToString();

            try
            {
                string jwsStr = token.ToString().Substring("Bearer ".Length).Trim();

                if (token.Length >= 128)
                {
                    TokenModel tkm = TokenHelper.SerializeJwt(jwsStr);
                    //提取tokenModel中的Sub属性进行authorize认证

                    var claimList = new RoleHelper(tkm).Roles.Select(s => new Claim(ClaimTypes.Role, s));
                    //var claimList = new List<Claim>
                    //{
                    // new Claim(ClaimTypes.Role, tkm.Role),
                    //};
                    var identity = new ClaimsIdentity(claimList);
                    var principal = new ClaimsPrincipal(identity);
                    httpContext.User = principal;
                }
            }
            catch (Exception)
            {
                Console.WriteLine(nameof(TokenAuth) + " Error !");
                httpContext.Response.StatusCode = StatusCodes.Status400BadRequest;
                return httpContext.Response.WriteAsync(JsonConvert.SerializeObject(new {Status = httpContext.Response.StatusCode , Message = "Token 解析异常"}));
            }
            return next(httpContext);
        }
    }
}
